home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / gopher / Unix / xgopher.1.3 / save.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-25  |  34.1 KB  |  1,406 lines

  1. /* save.c
  2.    make the file save dialog popup, and manage it. */
  3.  
  4.      /*---------------------------------------------------------------*/
  5.      /* Xgopher        version 1.3     08 April 1993                  */
  6.      /*                version 1.2     20 November 1992               */
  7.      /*                version 1.1     20 April 1992                  */
  8.      /*                version 1.0     04 March 1992                  */
  9.      /* X window system client for the University of Minnesota        */
  10.      /*                                Internet Gopher System.        */
  11.      /* Allan Tuchman, University of Illinois at Urbana-Champaign     */
  12.      /*                Computing and Communications Services Office   */
  13.      /* Copyright 1992, 1993 by                                       */
  14.      /*           the Board of Trustees of the University of Illinois */
  15.      /* Permission is granted to freely copy and redistribute this    */
  16.      /* software with the copyright notice intact.                    */
  17.      /*---------------------------------------------------------------*/
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21.  
  22.  
  23. #include <X11/Intrinsic.h>
  24. #include <X11/StringDefs.h>
  25. #include <X11/Xaw/Box.h>
  26. #include <X11/Xaw/Command.h>
  27. #include <X11/Xaw/Dialog.h>
  28. #include <X11/Xaw/AsciiText.h>
  29. #include <X11/Xaw/Label.h>
  30. #include <X11/Shell.h>
  31.  
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34.  
  35. #include "compatR4.h"
  36. #include "gopher.h"
  37. #include "osdep.h"
  38. #include "appres.h"
  39. #include "globals.h"
  40. #include "xglobals.h"
  41. #include "gui.h"
  42. #include "misc.h"
  43.  
  44.  
  45. /* 
  46.     "Save" is single-threaded by issuing a grab nonexclusive when
  47.     poped up.  So it is safe to use these globals to store an open
  48.     file descriptor and other information.  Be careful if this
  49.     ever changes.
  50. */
  51. typedef enum {SAVE_copy, SAVE_displayedText} saveType;
  52.  
  53. #define OPENFLAGS_NEWFILE    (O_CREAT | O_EXCL | O_WRONLY)
  54. #define OPENFLAGS_OVERWRITE    (O_CREAT | O_TRUNC | O_WRONLY)
  55. #define OPENFLAGS_APPEND    (O_APPEND | O_WRONLY)
  56.  
  57. static    int        FDToSave;
  58. static    int        saveLen;
  59. static    gopherItemP    giSaved;
  60. static    XtPointer    tepSaved;
  61. /*
  62. static    BOOLEAN        (*copyProc)();
  63. */
  64. static    saveType    returnTo;
  65.  
  66. void    makeCD();
  67. void    makeDupFile();
  68.  
  69.  
  70. static Widget    topLevel;
  71. static Widget    saveShell;
  72. static Widget    fileNameText, dirPath;
  73. static Widget    fileErrMessage;
  74. static Widget    saveLabel1, saveLabel2;
  75.  
  76. static char    currentDir[PATH_NAME_LEN];
  77.  
  78. #define SAVE_POPUP_NAME        "savePopup"
  79.                 /* default values */
  80. static popupPosResources    placementSave = {
  81.     /* position at the top of the main panel, centered across */
  82.     from_widget, 0, 10, justify_top_left, justify_top_left, True, True
  83.     };
  84.  
  85. #define COPY_POPUP_NAME        "copyPopup"
  86.                 /* default values */
  87. static popupPosResources    placementCopy = {
  88.     /* position at the top of the main panel, centered across */
  89.     from_main, 0, 10, justify_top_left, justify_top_left, True, True
  90.     };
  91.  
  92. typedef enum {Dup_none, Dup_overwrite, Dup_again, Dup_append, Dup_cancel}
  93.     dupType;
  94.  
  95. static dupType duplicateName = Dup_none;
  96.  
  97.  
  98. /* saveOkProc
  99.    accept file name and complete the copy-to-file or the 
  100.    save-displayed-text command */
  101.  
  102. void
  103. saveOkProc(w, client_data, call_data)
  104. Widget        w;
  105. XtPointer    client_data, call_data;
  106. {
  107.     int        c;
  108.     char        *tempFile, *newFile, *p;
  109.     int        outFD;
  110.     BOOLEAN        rc;
  111.     char        message[MESSAGE_STRING_LEN];
  112.     struct stat    buf;
  113.     Arg        args[10];
  114.     Cardinal    n = 0;
  115.     int        openFlags;
  116.  
  117.     /* clear previous warning */
  118.  
  119.     n = 0;
  120.     XtSetArg(args[n], XtNlabel, "");  n++;
  121.     XtSetValues(fileErrMessage, args, n);
  122.  
  123.     /* get the file name */
  124.  
  125.     n = 0;
  126.     XtSetArg(args[n], XtNstring, &tempFile);  n++;
  127.     XtGetValues(fileNameText, args, n);
  128.  
  129.     newFile = tildePath(tempFile);
  130.  
  131.     for (p=newFile; isgraph(*p); p++) ;
  132.     if (*p != NULLC) {
  133.         /* truncated at first non-printable character */
  134.         *p = NULLC;
  135.     } 
  136.     if (*newFile == NULLC) {
  137.         sprintf(message, "Warning: This is not a legal file name");
  138.  
  139.         n = 0;
  140.         XtSetArg(args[n], XtNlabel, message);  n++;
  141.         XtSetValues(fileErrMessage, args, n);
  142.  
  143.         return;
  144.     }
  145.  
  146.     switch (duplicateName) {
  147.     case Dup_none:            /* first time through */
  148.     case Dup_again:            /* already informed user */
  149.         if (stat(newFile, &buf) == 0) {
  150.             displayDupFile(newFile);
  151.             return;
  152.         }
  153.         openFlags = OPENFLAGS_NEWFILE;
  154.         break;
  155.     case Dup_overwrite:
  156.         openFlags = OPENFLAGS_OVERWRITE;
  157.         break;
  158.     case Dup_append:
  159.         openFlags = OPENFLAGS_APPEND;
  160.         break;
  161.     case Dup_cancel:    /* should not actually get here */
  162.         XtPopdown(saveShell);
  163.         return;
  164.         break;
  165.     }
  166.  
  167.     if ((outFD = open(newFile, openFlags,
  168.                     SAVE_FILE_MODE)) < 0) {
  169.         perror("save");
  170.         sprintf(message, "Warning: The file cannot be opened");
  171.  
  172.         n = 0;
  173.         XtSetArg(args[n], XtNlabel, message);  n++;
  174.         XtSetValues(fileErrMessage, args, n);
  175.  
  176.         return;
  177.     }
  178.  
  179.     XtPopdown(saveShell);
  180.  
  181.     if (returnTo == SAVE_displayedText) {
  182.         rc = saveDisplayedText(outFD, tepSaved);
  183.     } else {
  184.         rc = GI_copyFromNet(outFD, giSaved, (char *) NULL);
  185.     }
  186.  
  187.     close(outFD);
  188.  
  189.     if (! rc) {
  190.         unlink( newFile );
  191.     }
  192.  
  193.     return;
  194. }
  195.  
  196.  
  197. /* SaveOk
  198.    accept the OK action from a keyboard <cr> instead of the OK button.
  199.    The <cr> translation is defined elsewhere.
  200.    Capitalized name is for X action proc convention. */
  201.  
  202. void
  203. SaveOk(w, event, parms, nparms)
  204. Widget        w;
  205. XEvent        *event;
  206. String        *parms;
  207. Cardinal    *nparms;
  208. {
  209.     saveOkProc(w, NULL, NULL);
  210.     return;
  211. }
  212.  
  213.  
  214. /* saveCancelProc
  215.    reject file name and do not process the save command */
  216.  
  217. void
  218. saveCancelProc(w, client_data, call_data)
  219. Widget        w;
  220. XtPointer    client_data, call_data;
  221. {
  222.     XtPopdown(saveShell);
  223. }
  224.  
  225.  
  226. /* SaveCancel
  227.    accept the cancel action from a translation.
  228.    Capitalized name is for X action proc convention. */
  229.  
  230. void
  231. SaveCancel(w, event, parms, nparms)
  232. Widget        w;
  233. XEvent        *event;
  234. String        *parms;
  235. Cardinal    *nparms;
  236. {
  237.     saveCancelProc(w, NULL, NULL);
  238.     return;
  239. }
  240.  
  241.  
  242. /* saveCdProc
  243.    display change directory panel */
  244.  
  245. void
  246. saveCdProc(w, client_data, call_data)
  247. Widget        w;
  248. XtPointer    client_data, call_data;
  249. {
  250.     Arg        args[10];
  251.     Cardinal    n = 0;
  252.  
  253.     displayCD();
  254.  
  255.     /* clear previous warning */
  256.  
  257.     n = 0;
  258.     XtSetArg(args[n], XtNlabel, "");  n++;
  259.     XtSetValues(fileErrMessage, args, n);
  260. }
  261.  
  262.  
  263. /* SaveCd
  264.    accept the change directory action from a translation.
  265.    Capitalized name is for X action proc convention. */
  266.  
  267. void
  268. SaveCd(w, event, parms, nparms)
  269. Widget        w;
  270. XEvent        *event;
  271. String        *parms;
  272. Cardinal    *nparms;
  273. {
  274.     saveCdProc(w, NULL, NULL);
  275.     return;
  276. }
  277.  
  278.  
  279. /* saveHelpProc
  280.    display save help information */
  281.  
  282. void
  283. saveHelpProc(w, client_data, call_data)
  284. Widget        w;
  285. XtPointer    client_data, call_data;
  286. {
  287.     showHelp("save-copy help");
  288. }
  289.  
  290.  
  291. /* SaveHelp
  292.    accept the change directory action from a translation.
  293.    Capitalized name is for X action proc convention. */
  294.  
  295. void
  296. SaveHelp(w, event, parms, nparms)
  297. Widget        w;
  298. XEvent        *event;
  299. String        *parms;
  300. Cardinal    *nparms;
  301. {
  302.     saveHelpProc(w, NULL, NULL);
  303.     return;
  304. }
  305.  
  306.  
  307. /* makeSaveDialog
  308.    create popup dialog for saving files */
  309.  
  310. void
  311. makeSaveDialog(top)
  312. Widget    top;
  313. {
  314.     Widget        okButton, cancelButton, cdButton, helpButton;
  315.     Widget        saveForm, dirLabel;
  316.     Arg        args[10];
  317.     Cardinal    n = 0;
  318.     Dimension    wid;
  319.     static XtActionsRec    saveActionsTable[] = {
  320.                 { "saveok", (XtActionProc) SaveOk },
  321.                 { "saveCancel", (XtActionProc) SaveCancel }
  322.                 };
  323.  
  324.     topLevel = top;
  325.  
  326.     n = 0;
  327.     XtSetArg(args[n], XtNtitle, "Save or Copy to a File");  n++;
  328.     saveShell = XtCreatePopupShell("saveShell", 
  329.                     transientShellWidgetClass,
  330.                     topLevel, args, n);
  331.  
  332.  
  333.     n = 0;
  334.     XtSetArg(args[n], XtNlabel, "Save text to file ...");  n++;
  335.     XtSetArg(args[n], XtNvalue, "");  n++;
  336.     saveForm= XtCreateManagedWidget("saveForm", 
  337.                     formWidgetClass,
  338.                     saveShell, args, n);
  339.  
  340.     /* create save directory label */
  341.  
  342.         n=0;
  343.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  344.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  345.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  346.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  347.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  348.  
  349.     dirLabel = XtCreateManagedWidget("dirLabel", labelWidgetClass,
  350.                     saveForm, args, n);
  351.  
  352.     /* create current directory text */
  353.  
  354.         n=0;
  355.         XtSetArg(args[n], XtNeditType, XawtextRead);  n++;
  356.         XtSetArg(args[n], XtNstring, "");  n++;
  357.         XtSetArg(args[n], XtNfromVert,  dirLabel);  n++;
  358.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  359.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  360.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  361.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  362.     dirPath = XtCreateManagedWidget("dirPath", asciiTextWidgetClass,
  363.                     saveForm, args, n);
  364.     setTextWidgetSize(dirPath, 50, 1);
  365.  
  366.     n=0;
  367.     XtSetArg(args[n], XtNwidth, &wid);  n++;
  368.     XtGetValues(dirPath, args, n);
  369.  
  370.  
  371.     /* create save labels */
  372.  
  373.         n=0;
  374.         XtSetArg(args[n], XtNfromVert,  dirPath);  n++;
  375.         XtSetArg(args[n], XtNwidth,    wid);  n++;
  376.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  377.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  378.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  379.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  380.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  381.     saveLabel1 = XtCreateManagedWidget("saveLabel1", labelWidgetClass,
  382.                     saveForm, args, n);
  383.  
  384.         n=0;
  385.         XtSetArg(args[n], XtNfromVert,  saveLabel1);  n++;
  386.         XtSetArg(args[n], XtNwidth,    wid);  n++;
  387.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  388.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  389.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  390.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  391.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  392.     saveLabel2 = XtCreateManagedWidget("saveLabel2", labelWidgetClass,
  393.                     saveForm, args, n);
  394.  
  395.     /* create file name text */
  396.  
  397.         n=0;
  398.         XtSetArg(args[n], XtNeditType,  XawtextEdit);  n++;
  399.         XtSetArg(args[n], XtNstring,    "");  n++;
  400.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  401.         XtSetArg(args[n], XtNfromVert,  saveLabel2);  n++;
  402.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  403.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  404.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  405.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  406.     fileNameText = XtCreateManagedWidget("fileName", asciiTextWidgetClass,
  407.                     saveForm, args, n);
  408.     XtOverrideTranslations(fileNameText, oneLineParsed);
  409.  
  410.  
  411.     /* create file name error message */
  412.  
  413.         n=0;
  414.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  415.         XtSetArg(args[n], XtNfromVert,  fileNameText);  n++;
  416.         XtSetArg(args[n], XtNlabel,     "");  n++;
  417.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  418.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  419.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  420.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  421.     fileErrMessage = XtCreateManagedWidget("fileErrMessage",
  422.                     labelWidgetClass,
  423.                     saveForm, args, n);
  424.  
  425.     /* create save ok button */
  426.  
  427.         n=0;
  428.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  429.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  430.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  431.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  432.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  433.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  434.                     saveForm, args, n);
  435.     XtAddCallback(okButton, XtNcallback, saveOkProc, NULL);
  436.  
  437.     /* create save cancel button */
  438.  
  439.         n=0;
  440.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  441.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  442.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  443.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  444.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  445.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  446.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  447.                     saveForm, args, n);
  448.     XtAddCallback(cancelButton, XtNcallback, saveCancelProc, NULL);
  449.  
  450.     /* create save change directory button */
  451.  
  452.         n=0;
  453.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  454.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  455.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  456.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  457.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  458.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  459.     cdButton = XtCreateManagedWidget("chdir", commandWidgetClass, 
  460.                     saveForm, args, n);
  461.         XtAddCallback(cdButton, XtNcallback, saveCdProc, NULL);
  462.  
  463.     /* create save help button */
  464.  
  465.         n=0;
  466.         XtSetArg(args[n], XtNfromVert,  fileErrMessage);  n++;
  467.         XtSetArg(args[n], XtNfromHoriz, cdButton);  n++;
  468.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  469.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  470.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  471.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  472.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  473.                     saveForm, args, n);
  474.     XtAddCallback(helpButton, XtNcallback, saveHelpProc, NULL);
  475.  
  476.     XtAppAddActions(appcon, saveActionsTable, XtNumber(saveActionsTable));
  477.  
  478.     XtSetKeyboardFocus(saveForm, fileNameText);
  479.  
  480.         /* for ICCCM window manager protocol complience */
  481.  
  482.         XtOverrideTranslations (saveShell,
  483.             XtParseTranslationTable ("<Message>WM_PROTOCOLS: saveCancel()"));
  484.         XtRealizeWidget(saveShell);
  485.         (void) XSetWMProtocols (XtDisplay(saveShell),
  486.              XtWindow(saveShell), &wmDeleteAtom, 1);
  487.  
  488.  
  489.     /* find the popup placement for this shell */
  490.  
  491.     {
  492.     popupPosResources *resourcePlacement;
  493.  
  494.     resourcePlacement = getPopupPosResources(
  495.             SAVE_POPUP_NAME, POPUP_POS_CLASS, &placementSave);
  496.     bcopy( (char *) resourcePlacement, (char *) &placementSave,
  497.                 sizeof(popupPosResources) );
  498.  
  499.     resourcePlacement = getPopupPosResources(
  500.             COPY_POPUP_NAME, POPUP_POS_CLASS, &placementCopy);
  501.     bcopy( (char *) resourcePlacement, (char *) &placementCopy,
  502.                 sizeof(popupPosResources) );
  503.     }
  504.  
  505.  
  506.     makeCD(saveShell);
  507.     makeDupFile(saveShell);
  508.     
  509. }
  510.  
  511.  
  512. /* saveRequest
  513.    enable popup dialog for saving files */
  514.  
  515. void
  516. saveRequest(textShell, tep)
  517. Widget        textShell;
  518. XtPointer    tep;
  519. {
  520.  
  521.     Arg        args[10];
  522.     Cardinal    n = 0;
  523.     Position    x, y;
  524.     Dimension    w, h;
  525.     char        label[MESSAGE_STRING_LEN];
  526.     Widget        posFrom;
  527.     char        *dir;
  528.  
  529.     tepSaved = tep;
  530.     returnTo = SAVE_displayedText;
  531.  
  532.     duplicateName = Dup_none;
  533.  
  534.     dir = getwd(currentDir);
  535.     if (dir == (char *) NULL) {
  536.         fprintf (stderr, "Cannot determine current directory:\n%s\n",
  537.                 currentDir);
  538.         currentDir[0] = (char) NULL;
  539.     }
  540.  
  541.     n = 0;
  542.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  543.     XtSetValues(dirPath, args, n);
  544.  
  545.     /* should give name of subject that is being saved */
  546.  
  547.     n = 0;
  548.     XtSetArg(args[n], XtNlabel, "");  n++;
  549.     XtSetValues(saveLabel1, args, n);
  550.  
  551.     sprintf(label, "Enter a file name to save the text to");
  552.     n = 0;
  553.     XtSetArg(args[n], XtNlabel, label);  n++;
  554.     XtSetValues(saveLabel2, args, n);
  555.  
  556.     n = 0;
  557.     XtSetArg(args[n], XtNstring, "");  n++;
  558.     XtSetValues(fileNameText, args, n);
  559.  
  560.     n = 0;
  561.     XtSetArg(args[n], XtNtransientFor, textShell);  n++;
  562.     XtSetValues(saveShell, args, n);
  563.  
  564.     if (placementSave.positionFrom == from_widget) {
  565.         posFrom = (textShell != NULL) ? textShell : topLevel;
  566.     }  else {
  567.         posFrom = topLevel;
  568.     }
  569.  
  570.     /* clear previous warning */
  571.  
  572.     n = 0;
  573.     XtSetArg(args[n], XtNlabel, "");  n++;
  574.     XtSetValues(fileErrMessage, args, n);
  575.  
  576.     positionAPopup(saveShell, posFrom, &placementSave);
  577.  
  578.     XtPopup(saveShell, XtGrabExclusive);
  579.  
  580.     if (appResources->warpCursor) {
  581.                 XWarpPointer(XtDisplay(saveShell), None,
  582.                                 XtWindow(fileNameText),
  583.                                 0, 0, 0, 0,
  584.                                 10, 5);
  585.  
  586.         }
  587.  
  588.     return;
  589. }
  590.  
  591.  
  592. /* saveNetRequest
  593.    enable popup dialog for saving file directly from a gopher server */
  594.  
  595. void
  596. saveNetRequest(gi)
  597. gopherItemP    gi;
  598. {
  599.     char    *suggestedName;
  600.     int    len = -1;
  601.  
  602.     Arg        args[10];
  603.     Cardinal    n = 0;
  604.     Position    x, y;
  605.     Dimension    w, h;
  606.     char        label[MESSAGE_STRING_LEN];
  607.     char        *dir;
  608.  
  609.     saveLen = len;
  610.     giSaved = gi;
  611.     /* copyProc = gi->sc->copyTypeProc; */
  612.     returnTo = SAVE_copy;
  613.  
  614.     duplicateName = Dup_none;
  615.  
  616.     dir = getwd(currentDir);
  617.     if (dir == (char *) NULL) {
  618.         fprintf (stderr, "Cannot determine current directory:\n%s\n",
  619.                 currentDir);
  620.         currentDir[0] = (char) NULL;
  621.     }
  622.  
  623.     n = 0;
  624.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  625.     XtSetValues(dirPath, args, n);
  626.  
  627.     /* get the last component of the name.  If there is no '/' in
  628.        the path name, be suspicious and send NULL. */
  629.  
  630.     suggestedName = rindex(vStringValue(&(gi->selector)), '/');
  631.     if (suggestedName != NULL) suggestedName++;
  632.  
  633.     /* should give name of subject that is being saved */
  634.  
  635.     sprintf(label, "Enter a file name to receive contents of:");
  636.     n = 0;
  637.     XtSetArg(args[n], XtNlabel, label);  n++;
  638.     XtSetValues(saveLabel1, args, n);
  639.  
  640.     sprintf(label, "\"%s\"", USER_STRING(gi));
  641.     n = 0;
  642.     XtSetArg(args[n], XtNlabel, label);  n++;
  643.     XtSetValues(saveLabel2, args, n);
  644.  
  645.     n = 0;
  646.     if (suggestedName != NULL) {
  647.         XtSetArg(args[n], XtNstring, suggestedName);  n++;
  648.     } else {
  649.         XtSetArg(args[n], XtNstring, "");  n++;
  650.     }
  651.     XtSetValues(fileNameText, args, n);
  652.  
  653.     /* clear previous warning */
  654.  
  655.     n = 0;
  656.     XtSetArg(args[n], XtNlabel, "");  n++;
  657.     XtSetValues(fileErrMessage, args, n);
  658.  
  659.     positionAPopup(saveShell, topLevel, &placementCopy);
  660.  
  661.     XtPopup(saveShell, XtGrabExclusive);
  662.  
  663.     return;
  664. }
  665.  
  666.  
  667. void
  668. dupWrite()
  669. {
  670.     duplicateName = Dup_overwrite;
  671.     saveOkProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  672.     return;
  673. }
  674.  
  675.  
  676. void
  677. dupAppend()
  678. {
  679.     duplicateName = Dup_append;
  680.     saveOkProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  681.     return;
  682. }
  683.  
  684.  
  685. void
  686. dupChange()
  687. {
  688.     duplicateName = Dup_again;
  689.     return;
  690. }
  691.  
  692.  
  693. void
  694. dupCancel()
  695. {
  696.     duplicateName = Dup_cancel;
  697.     saveCancelProc((Widget) NULL, (XtPointer) NULL, (XtPointer) NULL);
  698.     return;
  699. }
  700.  
  701.  
  702. /* ====================================================================== */
  703. /* Change Directory popup                                                 */
  704. /* ====================================================================== */
  705.  
  706. static Widget    cdParent;
  707. static Widget    cdShell;
  708. static Widget    cdErrMessage;
  709. static Widget    cdPathName;
  710.  
  711. #define CD_POPUP_NAME        "cdPopup"
  712.                 /* default values */
  713. static popupPosResources    placementCD = {
  714.     /* position on the parent shell, centered near the left bottom */
  715.     from_widget, 0, 33, justify_top_left, justify_top_left, True, True
  716.     };
  717.  
  718.  
  719. /* cdOkProc
  720.    accept change directory command */
  721.  
  722. void
  723. cdOkProc(w, client_data, call_data)
  724. Widget        w;
  725. XtPointer    client_data, call_data;
  726. {
  727.     char        *path, *tempPath;
  728.     struct stat    buf;
  729.     char        message[MESSAGE_STRING_LEN];
  730.     Arg        args[10];
  731.     Cardinal    n = 0;
  732.  
  733.  
  734.     /* clear error text */
  735.  
  736.     n = 0;
  737.     XtSetArg(args[n], XtNlabel, "");  n++;
  738.     XtSetValues(cdErrMessage, args, n);
  739.  
  740.     /* ensure that the selected path exists and is writable */
  741.  
  742.     n = 0;
  743.     XtSetArg(args[n], XtNstring, &tempPath);  n++;
  744.     XtGetValues(cdPathName, args, n);
  745.  
  746.     path = tildePath(tempPath);
  747.  
  748.     if (stat(path, &buf) != 0) {
  749.         /* file/directory doesn't exist */
  750.  
  751.         fprintf (stderr, "%s does not exist\n", path);
  752.         sprintf (message, "This directory does not exist");
  753.  
  754.         n = 0;
  755.         XtSetArg(args[n], XtNlabel, message);  n++;
  756.         XtSetValues(cdErrMessage, args, n);
  757.  
  758.         return;
  759.     }
  760.     else if ((buf.st_mode & S_IFDIR) == 0) {
  761.         /* not directory */
  762.  
  763.         fprintf (stderr, "%s is not a directory\n", path);
  764.         sprintf (message, "This is not a directory");
  765.  
  766.         n = 0;
  767.         XtSetArg(args[n], XtNlabel, message);  n++;
  768.         XtSetValues(cdErrMessage, args, n);
  769.  
  770.         return;
  771.     }
  772.     else if (! isWriteableMode(&buf)) {
  773.         /* not writable */
  774.  
  775.         fprintf (stderr, "%s is not writeable\n", path);
  776.         sprintf (message, "You cannot write to this directory");
  777.  
  778.         n = 0;
  779.         XtSetArg(args[n], XtNlabel, message);  n++;
  780.         XtSetValues(cdErrMessage, args, n);
  781.  
  782.         return;
  783.     }
  784.  
  785.     if (chdir(path) != 0) {
  786.         perror("save");
  787.  
  788.         fprintf (stderr, "Cannot change to directory:\n%s\n",
  789.                 path);
  790.         sprintf (message, "You cannot change to this directory");
  791.  
  792.         n = 0;
  793.         XtSetArg(args[n], XtNlabel, message);  n++;
  794.         XtSetValues(cdErrMessage, args, n);
  795.  
  796.         return;
  797.     }
  798.  
  799.     XtPopdown (cdShell);
  800.  
  801.     strcpy(currentDir, path);
  802.  
  803.     n = 0;
  804.     XtSetArg(args[n], XtNstring, currentDir);  n++;
  805.     XtSetValues(dirPath, args, n);
  806.  
  807.     return;
  808. }
  809.  
  810.  
  811. /* CDOk
  812.    accept the OK action from a keyboard <cr> instead of the OK button.
  813.    The <cr> translation is defined elsewhere.
  814.    Capitalized name is for X action proc convention. */
  815.  
  816. void
  817. CDOk(w, event, parms, nparms)
  818. Widget        w;
  819. XEvent        *event;
  820. String        *parms;
  821. Cardinal    *nparms;
  822. {
  823.     cdOkProc(w, NULL, NULL);
  824.     return;
  825. }
  826.  
  827.  
  828. /* cdCancelProc
  829.    cancel change directory dialog */
  830.  
  831. void
  832. cdCancelProc(w, client_data, call_data)
  833. Widget        w;
  834. XtPointer    client_data, call_data;
  835. {
  836.     XtPopdown(cdShell);
  837. }
  838.  
  839.  
  840. /* CDCancel
  841.    accept the Cancel action from a keyboard <cr> instead of the Cancel button.
  842.    Capitalized name is for X action proc convention. */
  843.  
  844. void
  845. CDCancel(w, event, parms, nparms)
  846. Widget        w;
  847. XEvent        *event;
  848. String        *parms;
  849. Cardinal    *nparms;
  850. {
  851.     cdCancelProc(w, NULL, NULL);
  852.     return;
  853. }
  854.  
  855.  
  856. /* cdHelpProc
  857.    give help for change directory dialog */
  858.  
  859. void
  860. cdHelpProc(w, client_data, call_data)
  861. Widget        w;
  862. XtPointer    client_data, call_data;
  863. {
  864.     showHelp("change dir help");
  865. }
  866.  
  867.  
  868. /* CDHelp
  869.    accept the Help action from a keyboard <cr> instead of the Help button.
  870.    Capitalized name is for X action proc convention. */
  871.  
  872. void
  873. CDHelp(w, event, parms, nparms)
  874. Widget        w;
  875. XEvent        *event;
  876. String        *parms;
  877. Cardinal    *nparms;
  878. {
  879.     cdHelpProc(w, NULL, NULL);
  880.     return;
  881. }
  882.  
  883.  
  884. /* displayCD
  885.    pop up the change diretory panel */
  886.  
  887. displayCD()
  888. {
  889.     Arg        args[10];
  890.     Cardinal    n = 0;
  891.  
  892.     /* clear previous directory name and error text */
  893.  
  894.     n = 0;
  895.     XtSetArg(args[n], XtNstring, "");  n++;
  896.     XtSetValues(cdPathName, args, n);
  897.  
  898.     n = 0;
  899.     XtSetArg(args[n], XtNstring, "");  n++;
  900.     XtSetValues(cdErrMessage, args, n);
  901.  
  902.     positionAPopup(cdShell, cdParent, &placementCD);
  903.     
  904.     XtPopup (cdShell, XtGrabExclusive);
  905. }
  906.  
  907.  
  908. /* makeCD
  909.    create change directory dialog */
  910.  
  911. void
  912. makeCD(top)
  913. Widget    top;
  914. {
  915.     Widget        okButton, cancelButton, helpButton;
  916.     Widget        dirLabel;
  917.     Widget        cdForm;
  918.     Arg        args[10];
  919.     Cardinal    n = 0;
  920.     Dimension    wid;
  921.     static XtActionsRec    cdActionsTable[] = {
  922.                 { "cdok", (XtActionProc) CDOk },
  923.                 { "cdCancel", (XtActionProc) CDCancel },
  924.                 { "cdHelp", (XtActionProc) CDHelp },
  925.                 };
  926.  
  927.     cdParent = top;
  928.  
  929.         n = 0;
  930.         XtSetArg(args[n], XtNtitle, "Change Working Directory");  n++;
  931.         XtSetArg(args[n], XtNtransientFor, cdParent);  n++;
  932.     cdShell = XtCreatePopupShell("cdShell", transientShellWidgetClass,
  933.                     cdParent, args, n);
  934.  
  935.         n = 0;
  936.     cdForm= XtCreateManagedWidget("cdForm", formWidgetClass,
  937.                     cdShell, args, n);
  938.  
  939.     /* create cd label */
  940.  
  941.         n=0;
  942.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  943.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  944.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  945.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  946.  
  947.     dirLabel = XtCreateManagedWidget("cdLabel", labelWidgetClass,
  948.                     cdForm, args, n);
  949.  
  950.     /* create cd text */
  951.  
  952.         n=0;
  953.         XtSetArg(args[n], XtNeditType, XawtextEdit);  n++;
  954.         XtSetArg(args[n], XtNstring, "");  n++;
  955.         XtSetArg(args[n], XtNfromVert,  dirLabel);  n++;
  956.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  957.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  958.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  959.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  960.     cdPathName = XtCreateManagedWidget("cdPathName", asciiTextWidgetClass,
  961.                     cdForm, args, n);
  962.     setTextWidgetSize(cdPathName, 50, 1);
  963.     XtOverrideTranslations(cdPathName, oneLineParsed);
  964.  
  965.     n=0;
  966.     XtSetArg(args[n], XtNwidth, &wid);  n++;
  967.     XtGetValues(dirPath, args, n);
  968.  
  969.  
  970.     /* create cd error message */
  971.  
  972.         n=0;
  973.         XtSetArg(args[n], XtNwidth,     wid);  n++;
  974.         XtSetArg(args[n], XtNfromVert,  cdPathName);  n++;
  975.         XtSetArg(args[n], XtNlabel,     " ");  n++;
  976.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  977.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  978.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  979.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  980.     cdErrMessage = XtCreateManagedWidget("cdErrMessage", labelWidgetClass,
  981.                     cdForm, args, n);
  982.  
  983.     /* create cd ok button */
  984.  
  985.         n=0;
  986.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  987.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  988.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  989.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  990.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  991.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  992.                     cdForm, args, n);
  993.     XtAddCallback(okButton, XtNcallback, cdOkProc, NULL);
  994.  
  995.     /* create cd cancel button */
  996.  
  997.         n=0;
  998.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  999.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  1000.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1001.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1002.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1003.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1004.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  1005.                     cdForm, args, n);
  1006.     XtAddCallback(cancelButton, XtNcallback, cdCancelProc, NULL);
  1007.  
  1008.     /* create cd help button */
  1009.  
  1010.         n=0;
  1011.         XtSetArg(args[n], XtNfromVert,  cdErrMessage);  n++;
  1012.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  1013.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1014.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1015.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1016.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1017.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  1018.                     cdForm, args, n);
  1019.     XtAddCallback(helpButton, XtNcallback, cdHelpProc, NULL);
  1020.  
  1021.  
  1022.     XtAppAddActions(appcon, cdActionsTable, XtNumber(cdActionsTable));
  1023.  
  1024.     XtSetKeyboardFocus(cdForm, cdPathName);
  1025.  
  1026.         /* for ICCCM window manager protocol complience */
  1027.  
  1028.         XtOverrideTranslations (cdShell,
  1029.             XtParseTranslationTable ("<Message>WM_PROTOCOLS: cdCancel()"));
  1030.         XtRealizeWidget(cdShell);
  1031.         (void) XSetWMProtocols (XtDisplay(cdShell),
  1032.              XtWindow(cdShell), &wmDeleteAtom, 1);
  1033.  
  1034.  
  1035.     /* find the popup placement for this shell */
  1036.  
  1037.     {
  1038.     popupPosResources *resourcePlacement;
  1039.  
  1040.     resourcePlacement = getPopupPosResources(
  1041.             CD_POPUP_NAME, POPUP_POS_CLASS, &placementCD);
  1042.     bcopy( (char *) resourcePlacement, (char *) &placementCD,
  1043.                 sizeof(popupPosResources) );
  1044.     }
  1045. }
  1046.  
  1047.  
  1048. /* ====================================================================== */
  1049. /* File exists already popup                                              */
  1050. /* ====================================================================== */
  1051.  
  1052. static Widget    dupFileParent;
  1053. static Widget    dupFileShell;
  1054. static Widget    dupFileLabelFN;
  1055.  
  1056. #define DUPFILE_POPUP_NAME        "dupFilePopup"
  1057.                 /* default values */
  1058. static popupPosResources    placementDupFile = {
  1059.     /* position on the parent shell, centered, with bottoms aligned */
  1060.     from_widget, 50, 90, justify_center, justify_bottom_right, True, True
  1061.     };
  1062.  
  1063.  
  1064. /* dupFileOkProc
  1065.    accept overwrite contents command */
  1066.  
  1067. void
  1068. dupFileOkProc(w, client_data, call_data)
  1069. Widget        w;
  1070. XtPointer    client_data, call_data;
  1071. {
  1072.     XtPopdown (dupFileShell);
  1073.  
  1074.     dupWrite();
  1075.     return;
  1076. }
  1077.  
  1078.  
  1079. /* DupFileOk
  1080.    accept the OK action from a keyboard <cr> instead of the OK button.
  1081.    The <cr> translation is defined elsewhere.
  1082.    Capitalized name is for X action proc convention. */
  1083.  
  1084. void
  1085. DupFileOk(w, event, parms, nparms)
  1086. Widget        w;
  1087. XEvent        *event;
  1088. String        *parms;
  1089. Cardinal    *nparms;
  1090. {
  1091.     dupFileOkProc(w, NULL, NULL);
  1092.     return;
  1093. }
  1094.  
  1095.  
  1096. /* dupFileAppendProc
  1097.    accept append contents command */
  1098.  
  1099. void
  1100. dupFileAppendProc(w, client_data, call_data)
  1101. Widget        w;
  1102. XtPointer    client_data, call_data;
  1103. {
  1104.     XtPopdown (dupFileShell);
  1105.  
  1106.     dupAppend();
  1107.     return;
  1108. }
  1109.  
  1110.  
  1111. /* DupFileAppend
  1112.    accept the append action from a keyboard action instead of the append button.
  1113.    Capitalized name is for X action proc convention. */
  1114.  
  1115. void
  1116. DupFileAppend(w, event, parms, nparms)
  1117. Widget        w;
  1118. XEvent        *event;
  1119. String        *parms;
  1120. Cardinal    *nparms;
  1121. {
  1122.     dupFileAppendProc(w, NULL, NULL);
  1123.     return;
  1124. }
  1125.  
  1126.  
  1127. /* dupFileChangeProc
  1128.    change this save request because duplicate file name */
  1129.  
  1130. void
  1131. dupFileChangeProc(w, client_data, call_data)
  1132. Widget        w;
  1133. XtPointer    client_data, call_data;
  1134. {
  1135.     XtPopdown(dupFileShell);
  1136.  
  1137.     dupChange();
  1138. }
  1139.  
  1140.  
  1141. /* DupFileChange
  1142.    accept the Change action from a keyboard action instead of the Change button.
  1143.    Capitalized name is for X action proc convention. */
  1144.  
  1145. void
  1146. DupFileChange(w, event, parms, nparms)
  1147. Widget        w;
  1148. XEvent        *event;
  1149. String        *parms;
  1150. Cardinal    *nparms;
  1151. {
  1152.     dupFileChangeProc(w, NULL, NULL);
  1153.     return;
  1154. }
  1155.  
  1156.  
  1157. /* dupFileCancelProc
  1158.    cancel this save request because duplicate file name */
  1159.  
  1160. void
  1161. dupFileCancelProc(w, client_data, call_data)
  1162. Widget        w;
  1163. XtPointer    client_data, call_data;
  1164. {
  1165.     XtPopdown(dupFileShell);
  1166.  
  1167.     dupCancel();
  1168. }
  1169.  
  1170.  
  1171. /* DupFileCancel
  1172.    accept the Cancel action from a keyboard action instead of the Cancel button.
  1173.    Capitalized name is for X action proc convention. */
  1174.  
  1175. void
  1176. DupFileCancel(w, event, parms, nparms)
  1177. Widget        w;
  1178. XEvent        *event;
  1179. String        *parms;
  1180. Cardinal    *nparms;
  1181. {
  1182.     dupFileCancelProc(w, NULL, NULL);
  1183.     return;
  1184. }
  1185.  
  1186.  
  1187. /* dupFileHelpProc
  1188.    give help for duplicate file name dialog */
  1189.  
  1190. void
  1191. dupFileHelpProc(w, client_data, call_data)
  1192. Widget        w;
  1193. XtPointer    client_data, call_data;
  1194. {
  1195.     showHelp("dup file help");
  1196. }
  1197.  
  1198.  
  1199. /* DupFileHelp
  1200.    accept the Help action from a keyboard action instead of the Help button.
  1201.    Capitalized name is for X action proc convention. */
  1202.  
  1203. void
  1204. DupFileHelp(w, event, parms, nparms)
  1205. Widget        w;
  1206. XEvent        *event;
  1207. String        *parms;
  1208. Cardinal    *nparms;
  1209. {
  1210.     dupFileHelpProc(w, NULL, NULL);
  1211.     return;
  1212. }
  1213.  
  1214.  
  1215. /* displayDupFile
  1216.    pop up the file already exists (duplicate file) panel */
  1217.  
  1218. displayDupFile(path)
  1219. char    *path;
  1220. {
  1221.     Arg        args[10];
  1222.     Cardinal    n = 0;
  1223.  
  1224.     n = 0;
  1225.     XtSetArg(args[n], XtNlabel, path);  n++;
  1226.     XtSetValues(dupFileLabelFN, args, n);
  1227.  
  1228.     positionAPopup(dupFileShell, dupFileParent, &placementDupFile);
  1229.     
  1230.     XtPopup (dupFileShell, XtGrabExclusive);
  1231. }
  1232.  
  1233.  
  1234. /* makeDupFile
  1235.    create duplicate file name notice dialog */
  1236.  
  1237. void
  1238. makeDupFile(top)
  1239. Widget    top;
  1240. {
  1241.     Widget        okButton, appendButton, changeButton,
  1242.             cancelButton, helpButton;
  1243.     Widget        label1, label2;
  1244.     Widget        dupFileForm;
  1245.     Arg        args[10];
  1246.     Cardinal    n = 0;
  1247.     Dimension    wid;
  1248.     static XtActionsRec    dupFileActionsTable[] = {
  1249.                 { "dupFileok", (XtActionProc) DupFileOk },
  1250.                  { "dupFileappend", (XtActionProc) DupFileAppend },
  1251.                  { "dupFileCancel", (XtActionProc) DupFileCancel },
  1252.                 { "dupFileHelp", (XtActionProc) DupFileHelp },
  1253.                 };
  1254.  
  1255.     dupFileParent = top;
  1256.  
  1257.         n = 0;
  1258.         XtSetArg(args[n], XtNtitle, "File Already Exists");  n++;
  1259.         XtSetArg(args[n], XtNtransientFor, dupFileParent);  n++;
  1260.     dupFileShell = XtCreatePopupShell("dupFileShell",
  1261.                     transientShellWidgetClass,
  1262.                     dupFileParent, args, n);
  1263.  
  1264.         n = 0;
  1265.     dupFileForm= XtCreateManagedWidget("dupFileForm", formWidgetClass,
  1266.                     dupFileShell, args, n);
  1267.  
  1268.     /* create dupFile label */
  1269.  
  1270.         n=0;
  1271.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1272.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1273.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1274.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1275.  
  1276.     label1 = XtCreateManagedWidget("label1", labelWidgetClass,
  1277.                     dupFileForm, args, n);
  1278.  
  1279.     /* create dupFile file name label */
  1280.  
  1281.         n=0;
  1282.         XtSetArg(args[n], XtNfromHoriz, label1);  n++;
  1283.         XtSetArg(args[n], XtNjustify,   XtJustifyLeft);  n++;
  1284.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1285.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1286.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1287.         XtSetArg(args[n], XtNright,     XawChainRight);  n++;
  1288.  
  1289.     dupFileLabelFN = XtCreateManagedWidget("labelFile", labelWidgetClass,
  1290.                     dupFileForm, args, n);
  1291.     {
  1292.         Dimension    w, h;
  1293.  
  1294.         getTextSize(dupFileLabelFN, 40, 1, &w, &h);
  1295.         n=0;
  1296.         XtSetArg(args[n], XtNwidth, w);  n++;
  1297.         XtSetValues(dupFileLabelFN, args, n);
  1298.     }
  1299.  
  1300.     /* create dupFile label */
  1301.  
  1302.         n=0;
  1303.         XtSetArg(args[n], XtNfromVert,  label1);  n++;
  1304.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1305.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1306.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1307.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1308.  
  1309.     label2 = XtCreateManagedWidget("label2", labelWidgetClass,
  1310.                     dupFileForm, args, n);
  1311.  
  1312.  
  1313.     /* create dupFile ok button */
  1314.  
  1315.         n=0;
  1316.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1317.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1318.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1319.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1320.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1321.     okButton = XtCreateManagedWidget("ok", commandWidgetClass,
  1322.                     dupFileForm, args, n);
  1323.     XtAddCallback(okButton, XtNcallback, dupFileOkProc, NULL);
  1324.  
  1325.  
  1326.     /* create dupFile cancel button */
  1327.  
  1328.         n=0;
  1329.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1330.         XtSetArg(args[n], XtNfromHoriz, okButton);  n++;
  1331.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1332.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1333.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1334.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1335.     cancelButton = XtCreateManagedWidget("cancel", commandWidgetClass,
  1336.                     dupFileForm, args, n);
  1337.     XtAddCallback(cancelButton, XtNcallback, dupFileCancelProc, NULL);
  1338.  
  1339.  
  1340.     /* create dupFile append button */
  1341.  
  1342.         n=0;
  1343.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1344.         XtSetArg(args[n], XtNfromHoriz, cancelButton);  n++;
  1345.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1346.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1347.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1348.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1349.     appendButton = XtCreateManagedWidget("append", commandWidgetClass,
  1350.                     dupFileForm, args, n);
  1351.     XtAddCallback(appendButton, XtNcallback, dupFileAppendProc, NULL);
  1352.  
  1353.     /* create dupFile change button */
  1354.  
  1355.         n=0;
  1356.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1357.         XtSetArg(args[n], XtNfromHoriz, appendButton);  n++;
  1358.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1359.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1360.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1361.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1362.     changeButton = XtCreateManagedWidget("change", commandWidgetClass,
  1363.                     dupFileForm, args, n);
  1364.     XtAddCallback(changeButton, XtNcallback, dupFileChangeProc, NULL);
  1365.  
  1366.     /* create dupFile help button */
  1367.  
  1368.         n=0;
  1369.         XtSetArg(args[n], XtNfromVert,  label2);  n++;
  1370.         XtSetArg(args[n], XtNfromHoriz, changeButton);  n++;
  1371.         XtSetArg(args[n], XtNtop,       XawChainTop);  n++;
  1372.         XtSetArg(args[n], XtNbottom,    XawChainTop);  n++;
  1373.         XtSetArg(args[n], XtNleft,      XawChainLeft);  n++;
  1374.         XtSetArg(args[n], XtNright,     XawChainLeft);  n++;
  1375.     helpButton = XtCreateManagedWidget("help", commandWidgetClass,
  1376.                     dupFileForm, args, n);
  1377.     XtAddCallback(helpButton, XtNcallback, dupFileHelpProc, NULL);
  1378.  
  1379.  
  1380.     XtAppAddActions(appcon, dupFileActionsTable,
  1381.                 XtNumber(dupFileActionsTable));
  1382.  
  1383.  
  1384.         /* for ICCCM window manager protocol complience */
  1385.  
  1386.         XtOverrideTranslations (dupFileShell,
  1387.             XtParseTranslationTable (
  1388.                 "<Message>WM_PROTOCOLS: dupFileCancel()"));
  1389.         XtRealizeWidget(dupFileShell);
  1390.         (void) XSetWMProtocols (XtDisplay(dupFileShell),
  1391.              XtWindow(dupFileShell), &wmDeleteAtom, 1);
  1392.  
  1393.  
  1394.     /* find the popup placement for this shell */
  1395.  
  1396.     {
  1397.     popupPosResources *resourcePlacement;
  1398.  
  1399.     resourcePlacement = getPopupPosResources(
  1400.         DUPFILE_POPUP_NAME, POPUP_POS_CLASS, &placementDupFile);
  1401.     bcopy( (char *) resourcePlacement, (char *) &placementDupFile,
  1402.                 sizeof(popupPosResources) );
  1403.     }
  1404.  
  1405. }
  1406.